package org.study.minio.boot.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.study.minio.boot.config.MinioConstant;
import org.study.minio.boot.util.MinioUtils;

/**
 * 作用描述
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2023年12月14日
 */
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/minio1")
public class FileUploadMinio1Controller {
    @RequestMapping
    public ModelAndView toChatGpt1() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("upload1");
        return modelAndView;
    }

    @PostMapping("/chunks")
    public ResponseEntity<String> uploadChunk(@RequestParam("file") MultipartFile file,
                                              @RequestParam("chunkNumber") int chunkNumber,
                                              @RequestParam("totalChunks") int totalChunks,
                                              @RequestParam("identifier") String identifier) {
        try {
            // 检查Bucket是否存在，不存在则创建
            boolean createBucket = MinioUtils.createBucket(MinioConstant.BUCKET_TEST);
            // 生成唯一的对象名称（文件名）
            String objectName = identifier.replace(".", "");
            // 获取当前文件的分片数据
            byte[] chunkData = file.getBytes();
            // 将分片数据上传到MinIO对象存储
            MinioUtils.uploadFile(MinioConstant.BUCKET_TEST, objectName + "/" + identifier + "-" + chunkNumber, chunkData);
            if (chunkNumber == totalChunks - 1) {
                // 如果是最后一个分片，进行文件合并
                // String url = this.mergeChunksByMemory(identifier, objectName, totalChunks);
                String url = this.mergeChunksByMinio(identifier, objectName, totalChunks);
                return new ResponseEntity<>("文件上传成功，访问地址：" + url, HttpStatus.OK);
            }
            return new ResponseEntity<>("上传分片文件成功", HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>("上传分片文件异常：" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private String mergeChunksByMinio(String identifier, String objectName, int totalChunks) throws Exception {
        String url = MinioUtils.composeObject(MinioConstant.BUCKET_TEST, objectName, MinioConstant.BUCKET_TEST, identifier);
        log.info("文件合并后的位置：" + url);
        MinioUtils.deleteFolder(MinioConstant.BUCKET_TEST, objectName);
        return url;
    }

    private String mergeChunksByMemory(String identifier, String objectName, int totalChunks) throws Exception {
        // 创建最终合并后的文件
        byte[] mergedData = new byte[0];
        // 将所有分片数据合并
        for (int i = 0; i < totalChunks; i++) {
            byte[] chunkData = MinioUtils.getObjectByte(MinioConstant.BUCKET_TEST, objectName + "/" + identifier + "-" + i);
            mergedData = this.mergeByteArrays(mergedData, chunkData);
        }
        // 将合并后的数据上传为最终文件
        String url = MinioUtils.uploadFile(MinioConstant.BUCKET_TEST, objectName + "/" + identifier, mergedData);
        // 删除所有分片数据
        for (int i = 0; i < totalChunks; i++) {
            MinioUtils.removeFile(MinioConstant.BUCKET_TEST, objectName + "/" + identifier + "-" + i);
        }
        log.info("文件合并后的位置：" + url);
        return url;
    }

    private byte[] mergeByteArrays(byte[] array1, byte[] array2) {
        byte[] mergedArray = new byte[array1.length + array2.length];
        System.arraycopy(array1, 0, mergedArray, 0, array1.length);
        System.arraycopy(array2, 0, mergedArray, array1.length, array2.length);
        return mergedArray;
    }
}
